package Project4;

import java.util.*;

class FunctionTAC extends Statement{
	private String name;
	private ArrayList<Statement> statements;
	private boolean isMain = false;
	private Hashtable<String, Variable> variables = new Hashtable<String, Variable>();

	public FunctionTAC(String s){
		name = s;
	}

	public FunctionTAC(String s, boolean isMain){
		this(s);
		this.isMain = isMain;
	}

	public void addStatements(ArrayList<Statement> s){
		statements = s;
	}

	public void addVariables(Hashtable<String, Variable> v){
		this.variables = v;
		int i = 0;
		for(Variable var: v.values()){
			var.setOffset(i++);
		}
	}

	public String getName(){
		return name;
	}

	public String toString(){
		String r = name + ":\n";
		//allocate variable space
		if(variables.size() > 0)
		{
			r += "#variable declarations and allocation\n";
			r += "move $s0, $sp\n";
			r += "add $sp, $sp, " + variables.size()*4 + "\n";
		}
		
		//preserve stack as best as possible
		if(!isMain){
			r += "#preserve registers onto the stack (NOT OPTIMIZED)\n"; //s0-s7
			for(int i = 0; i < 8; i++){
				r += "sub $sp, $sp, 4\n";
				r += "sw $s"+i+ ", ($sp)\n";
			}
		}
		r+= "\n#method body for " + name + "\n";
		for(Statement s: statements){
			r += s;
		}
		if(!isMain){
			//restore stack
			r += "\n#restore registers from the stack (NOT OPTIMIZED)\n"; //s0-s7
			for(int i = 7; i > -1; i--){
				r += "lw $s"+i+ ", ($sp)\n";
				r += "add $sp, $sp, 4\n";
			}	
			//save variable (being returned, if applicable)
			//do the return
			r += "jr $ra\n";
		}
		r += "#---------------\n\n";
		return r;
	}
}
